const { DOMParser } = require('xmldom');
function iterator(doc, cb, depth = 0) {
  const $break = cb(doc, depth);
  if ($break) {
    return;
  }
  if (doc.childNodes) {
    // eslint-disable-next-line no-plusplus
    depth++;
    Object.values(doc.childNodes).forEach((c) => iterator(c, cb, depth));
  }
}

function deepFindOne(dom, filter) {
  let output;
  iterator(dom, (dom, depth) => {
    if (filter(dom, depth)) {
      output = output || dom;
      return true;
    }
    return false;
  });
  return output;
}

function deepFindAll(dom, filter) {
  const output = [];
  iterator(dom, (dom, depth) => {
    if (filter(dom, depth)) {
      output.push(dom);
    }
    return false;
  });
  return output;
}

function bubbleFindOne(dom, filter, level = 0) {
  if (filter(dom, level)) {
    return dom;
  }
  if (dom.parentNode) {
    // eslint-disable-next-line no-plusplus
    return bubbleFindOne(dom.parentNode, filter, ++level);
  }
  return null;
}

function parseXml(str) {
  const dom = new DOMParser().parseFromString(str.toString(), 'text/xml');
  return dom;
}

function getRelations(relsDom) {
  const relations = deepFindOne(relsDom, (n) => n.nodeName === 'Relationships');
  const relationMap = new Map();
  Object.values(relations.childNodes).forEach((node) => {
    if (node.nodeName === 'Relationship') {
      const target = node.getAttribute('Target');
      const relationId = node.getAttribute('Id');
      relationMap.set(relationId, target);
    }
  });
  return relationMap;
}

function getImageReplaceMap(dom) {
  const arr = deepFindAll(dom, (node) => node.nodeName === 'pic:cNvPr' && node.getAttribute('descr') && node.getAttribute('descr').startsWith('{%'));
  // console.log(arr.map(node => node.getAttribute('descr')));
  const replaceMap = new Map();
  arr.forEach((node) => {
    const pic = bubbleFindOne(node, (n) => n.nodeName === 'pic:pic');
    // console.log(pic);
    const n = deepFindOne(pic, (n) => n.nodeName === 'a:blip');
    const relationId = n.getAttribute('r:embed');
    const extractPattern = /\{%\s*(coverImg|header)\s*\}/;
    // console.log(node.getAttribute('descr'));
    const replacement = node.getAttribute('descr').match(extractPattern)[1];
    if (replacement) {
      replaceMap.set(relationId, replacement);
    }
  });
  return replaceMap;
}

module.exports = {
  parseXml,
  getRelations,
  getImageReplaceMap,
};
